/*
 * Niiuzu
 * Copyright (C) 2011  Thierry Nowak
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.niiuzu.client.screen.feed.filter;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.inject.Inject;
import com.mvp4g.client.annotation.Presenter;
import com.mvp4g.client.presenter.LazyPresenter;
import com.niiuzu.client.eventbus.FeedEventBus;
import com.niiuzu.client.screen.feed.filter.FeedFilterView.AddChannelResult;
import com.niiuzu.client.util.SessionClient;
import com.niiuzu.client.util.callback.AbstractCallback;
import com.niiuzu.shared.model.FeedChannel;
import com.niiuzu.shared.model.FeedChannelGroup;
import com.niiuzu.shared.model.UserSettings;
import com.niiuzu.shared.rpc.UserServiceAsync;

/**
 * Presenter dédié à la gestion des flux RSS.
 */
@Presenter(view = FeedFilterViewImpl.class)
public class FeedFilterPresenter extends
		LazyPresenter<FeedFilterView, FeedEventBus> {

	@Inject
	private UserServiceAsync userService;

	private ClickHandler lastRemoveClickHandler;

	private ClickHandler addChannelGroupClickHandler;

	private ClickHandler addChannelClickHandler;

	@Override
	public void bindView() {
		super.bindView();

		addChannelClickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				eventBus.newChannelAsked();
			}
		};
		view.getAddChannelHasClickHandlers().addClickHandler(
				addChannelClickHandler);

		addChannelGroupClickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				eventBus.newChannelGroupAsked();
			}
		};
		view.getAddChannelGroupHasClickHandlers().addClickHandler(
				addChannelGroupClickHandler);
	}

	/**
	 * Point d'entrée de cet écran.
	 * 
	 * @see FeedEventBus#channelFilterLoadingStarted()
	 */
	public void onChannelFilterLoadingStarted() {

		userService.retrieveUserSettings(new AbstractCallback<UserSettings>(
				eventBus) {
			@Override
			public void onSuccess(UserSettings result) {
				retrieveDefaultChannels(result);
			}
		});
	}

	/**
	 * Récupération du flux créé suite à un clic sur le bouton "ajouter".
	 */
	void recoverNewChannel(FeedChannel channel) {
		addAndBindChannel(channel);

		eventBus.channelListUpdated();
	}

	/**
	 * Ajoute un flux dans la liste et affecte les comportements aux composants
	 * créés.
	 */
	void addAndBindChannel(final FeedChannel channel) {
		SessionClient sessionClient = SessionClient.getInstance();

		sessionClient.addChannel(channel);

		FeedChannelGroup channelGroup = sessionClient
				.getGroupFromChannel(channel);

		StringBuffer channelName = new StringBuffer();
		channelName.append(channelGroup.getName());
		channelName.append(" - ");
		channelName.append(channel.getName());
		AddChannelResult result = view.addChannel(channelName.toString());

		// Bind de la suppression
		lastRemoveClickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				eventBus.channelOrGroupRemoveAsked(channel);
			}
		};
		result.getHasClickHandlers().addClickHandler(lastRemoveClickHandler);
	}

	/**
	 * Le presenter est prévenu que des flux viennent d'être supprimés.
	 * 
	 * @see FeedEventBus#channelsRemoved()
	 */
	public void onChannelsRemoved() {
		updateChannelList();
	}

	/**
	 * Le presenter est prévenu qu'un nouveau flux vient d'être créé.
	 * 
	 * @see FeedEventBus#channelCreated()
	 */
	public void onChannelCreated() {
		updateChannelList();
	}

	/**
	 * Le presenter est prévenu qu'un nouveau thème vient d'être créé.
	 * 
	 * @see FeedEventBus#channelGroupCreated()
	 */
	public void onChannelGroupCreated() {
		updateChannelList();
	}

	/**
	 * Mise à jour de la liste de flux avec le lancement d'un événement.
	 */
	private void updateChannelList() {
		SessionClient sessionClient = SessionClient.getInstance();

		view.clearChannelList();
		for (FeedChannel channel : sessionClient.getChannelArray()) {
			addAndBindChannel(channel);
		}

		eventBus.channelListUpdated();
	}

	/**
	 * Récupération des flux et thèmes créés au premier affichage de
	 * l'application.
	 */
	void retrieveDefaultChannels(UserSettings settings) {

		// Peuple la session avec les thèmes reçus
		for (FeedChannelGroup channelGroup : settings.getChannelGroups()) {
			SessionClient.getInstance().addChannelGroup(channelGroup);
		}

		// Peuple la session avec les flux reçus
		for (FeedChannel channel : settings.getChannels()) {
			addAndBindChannel(channel);
		}

		// Chargement de l'écran terminé
		eventBus.channelFilterLoaded(view);
	}

	/**
	 * Comportement affecté au dernier bouton de suppression de flux ajouté.
	 */
	ClickHandler getLastRemoveClickHandler() {
		return lastRemoveClickHandler;
	}

	/**
	 * Comportement d'un clic sur le composant de l'ajout de flux.
	 */
	public ClickHandler getAddChannelClickHandler() {
		return addChannelClickHandler;
	}

	/**
	 * Comportement d'un clic sur le composant de l'ajout de thèmes.
	 */
	public ClickHandler getAddChannelGroupClickHandler() {
		return addChannelGroupClickHandler;
	}

	/* ********************************************************************** */
	/* ********************************************************************** */
	/* ********************************************************************** */

	/**
	 * JUnit - Définit un mock pour {@link UserServiceAsync}.
	 */
	void setMockedUserService(UserServiceAsync mockedUserService) {
		this.userService = mockedUserService;
	}
}
